from django.shortcuts import render
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from django_redis import get_redis_connection

from goods.models import SKU
from . import serializers
import pickle
import base64


class CartView(GenericAPIView):
    serializer_class = serializers.CartSerializer

    # 重寫方法,讓未登陸用戶也能訪問該視圖
    def perform_authentication(self, request):
        pass

    # 新增購物車
    def post(self,request):
        # 獲取數據
        dict_data = request.data

        # 獲取序列化器
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 獲取數據
        sku_id = serializer.data.get("sku_id")
        count = serializer.data.get("count")
        selected = serializer.data.get("selected",True)

        try:
            user = request.user
        except Exception as e:
            user = None

        # 判斷用戶狀態
        if user and request.user.is_authenticated:
            # 獲取redis對象
            redis_conn = get_redis_connection("cart")

            # 增加購物車商品數量
            redis_conn.hincrby("cart_%s"%user.id,sku_id,count)

            if selected:
                redis_conn.sadd("cart_selected_%s"%user.id,sku_id)

            # 返回
            return Response(serializer.data)

        else:
            # 獲取cookie中購物車數據
            cookie_cart = request.COOKIES.get("cart")

            # 判斷是否有購物車數據,轉換字典數據
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 累加
            if sku_id in cookie_dict:
                count += cookie_dict[sku_id].get("count",0)

            # 設置新的數據到字典
            cookie_dict[sku_id] = {
                "count":count,
                "selected":selected
            }

            # 將字典轉換成字符串,寫入到cookie
            response = Response(status=status.HTTP_200_OK)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie("cart",cookie_cart)
            return response

    # 獲取購物車
    def get(self,request):
        # 獲取用戶數據
        try:
            user = request.user
        except Exception as e:
            user = None

        # 判斷用戶登陸狀態
        if user and request.user.is_authenticated:
            # 獲取redis中用戶購物車數據
            redis_conn = get_redis_connection("cart")
            redis_cart_dict = redis_conn.hgetall("cart_%s"%user.id)
            redis_cart_selected_list = redis_conn.smembers("cart_selected_%s"%user.id)

            # 數據拼接
            sku_list = []
            for sku_id, count in redis_cart_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "selected":sku_id in redis_cart_selected_list,
                    "default_image_url":sku.default_image_url,
                    "name":sku.name,
                    "price":sku.price,
                    "count":int(count),
                    "id":sku.id
                }
                sku_list.append(sku_dict)

            # 返回響應
            return Response(sku_list)
        else:
            # 獲取cookie中的數據
            cookie_cart = request.COOKIES.get("cart")

            # 轉換成字典
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 拼接數據
            sku_list = []
            for sku_id,count_selected in cookie_dict.items():
                sku = SKU.objects.get(id=sku_id)
                sku_dict = {
                    "selected":count_selected["selected"],
                    "default_image_url":sku.default_image_url,
                    "name":sku.name,
                    "price":sku.price,
                    "count":int(count_selected["count"]),
                    "id":sku.id
                }
                sku_list.append(sku_dict)

            # 返回響應
            return Response(sku_list)

    # 修改購物車
    def put(self,request):
        # 獲取參數
        dict_data = request.data

        # 獲取序列化器,校驗參數
        serializer = self.get_serializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 獲取數據
        sku_id = serializer.data.get("sku_id")
        count = serializer.data.get("count")
        selected = serializer.data.get("selected")

        try:
            user = request.user
        except Exception as e:
            user = None

        # 判斷用戶登陸狀態
        if user and request.user.is_authenticated:
            # 獲取redis中數據
            redis_conn = get_redis_connection("cart")

            # 修改
            redis_conn.hset("cart_%s"%user.id,sku_id,count)

            if selected:
                redis_conn.sadd("cart_selected_%s"%user.id,sku_id)
            else:
                redis_conn.srem("cart_selected_%s"%user.id,sku_id)

            # 返回
            return Response(serializer.data)
        else:
            # 獲取cookie中數據
            cookie_cart = request.COOKIES.get("cart")

            # 轉換字典
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 修改
            cookie_dict[sku_id] = {
                "count":count,
                "selected":selected
            }

            # 轉換成字符串並返回
            response = Response(serializer.data)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie("cart",cookie_cart)

            return response

    # 刪除購物車
    def delete(self,request):
        # 獲取參數
        dict_data = request.data

        # 創建序列化器,校驗參數
        serializer = serializers.CartDeleteSerializer(data=dict_data)
        serializer.is_valid(raise_exception=True)

        # 獲取數據
        sku_id = serializer.data.get("sku_id")

        try:
            user = request.user
        except Exception as e:
            user = None

        # 判斷用戶的登陸狀態
        if user and request.user.is_authenticated:
            # 刪除redis中的數據
            redis_conn = get_redis_connection("cart")
            redis_conn.hdel("cart_%s"%user.id,sku_id)
            redis_conn.srem("cart_selected_%s"%user.id,sku_id)

            # 返回響應
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            # 獲取cookie中的數據
            cookie_cart = request.COOKIES.get("cart")

            # 轉換字典
            cookie_dict = {}
            if cookie_cart:
                cookie_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))

            # 刪除
            if sku_id in cookie_dict:
                del cookie_dict[sku_id]

            # 返回響應
            response = Response(status=status.HTTP_204_NO_CONTENT)
            cookie_cart = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response.set_cookie("cart",cookie_cart)

            return response

